package client

import (
	. "chess_platform/internal/common"
	"chess_platform/models/client"
	"fmt"
	"github.com/astaxie/beego/orm"
	"strconv"
)

//[client]游戏配置
type GameController struct {
	GrantController
}

func (b *GameController) URLMapping() {
	b.Mapping("ListAreaGame", b.ListAreaGame)
	b.Mapping("GetLobbyServerIP", b.GetLobbyServerIP)
}

// @Title 区域游戏列表
// @Description 区域游戏列表
// @Param   page_size    body   int     true       "每页显示数量"
// @Param   page_index   body   int     true       "第几页"
// @Param   type         body   int     true       "游戏分类:0-所有游戏,1-麻将,2-扑克,3-字牌,4-其他"
// @Success 0 {object} []common.GameList 游戏列表
// @router /list-area-game [post]
func (b *GameController) ListAreaGame() {
	type Params struct {
		ListParams
		Type int64 `json:"type" valid:"Range(0,4)"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}
	/*
		1. 首先判断city_code是什么什么级别的，县(4)，市(3)
		2. 如果是县级，则先判断县级有没有游戏列表，如果有，则直接返回县级的游戏列表，
			如果没有就找上一级游戏列表，上一级也没有就找全国的，全国也没有就找全部游戏
		3. 如果是市级的，则先判断市级有没有游戏列表，如果有，则直接返回市级的游戏列表，
			如果也没有就找全国的，全国也没有就找全部游戏
	*/

	var cityCode int64
	user, err := client.QueryUserInfoById(b.Uid)
	if err != nil {
		LogClient.Error(fmt.Sprintf("获取用户(ID:%v)的区域编码失败:%v,使用默认区域北京(110100),请检查", b.Uid, err))
		cityCode = 110100
	} else {
		cityCode = user.CityCode
	}
	//先在缓存中找
	key := fmt.Sprintf("%v%v%v", KeyClientGameList, cityCode, p.Type)
	ok := IsRedisCacheExist(key)
	var value []orm.Params
	value, err = GetSliceCache(key)
	if err != nil {
		LogClient.Debug(fmt.Sprintf("city_code:%v获取缓存时报的信息:%v", cityCode, err))
	}

	parentType := CityParent[fmt.Sprintf("%v", cityCode)].ParentType
	if parentType == "3" { //说明city_code是县级
		parentCode := CityParent[fmt.Sprintf("%v", cityCode)].ParentCode
		LogClient.Debug(fmt.Sprintf("city_code:%v是县级的,所属的市级的city_code:%v", cityCode, parentCode))
		//这个key如果不存在,要从数据库里找
		if !ok {
			LogClient.Debug(fmt.Sprintf("县级的city_code:%v的缓存(key)不存在,要从mysql里获取", cityCode))
			value, err = getCountyAreaGame(key, cityCode, p.Type, user.Vip)
			if err != nil {
				LogClient.Error(b.DatabaseError(err.Error()))
				return
			}
			if len(value) == 0 {
				LogClient.Debug(fmt.Sprintf("县级的city_code:%v的缓存(key)不存在,从mysql里获取也没有游戏列表,下一步找所属市级的", cityCode))
			} else {
				LogClient.Debug(fmt.Sprintf("县级的city_code:%v的缓存(key)不存在,但从mysql里获取到了游戏列表", cityCode))
			}
		}
		//不管上面的key是否存在,如果value还是为空,要去找市级的
		if len(value) == 0 { //县级里的缓存里存在，但是内容为空，说明县级没有游戏,直接找市级的
			if ok {
				LogClient.Debug(fmt.Sprintf("县级的city_code:%v的缓存存在,但是为空数据,要从所属的市级city_code:%v里获取", cityCode, parentCode))
			} else {
				LogClient.Debug(fmt.Sprintf("县级的city_code:%v的缓存(key)不存在,要从所属的市级city_code:%v里获取", cityCode, parentCode))
			}
			key = fmt.Sprintf("%v%v%v", KeyClientGameList, parentCode, p.Type)
			value, err = getCityAreaGame(key, parentCode, p.Type, user.Vip)
			if err != nil {
				LogClient.Error(b.DatabaseError(err.Error()))
				return
			}
		} else if ok {
			LogClient.Debug(fmt.Sprintf("县级city_code:%v的缓存存在,且不为空", cityCode))
		}
	} else { //说明是市级的
		if len(value) == 0 { //缓存里不存在
			LogClient.Debug(fmt.Sprintf("市级city_code:%v的缓存不存在", cityCode))
			value, err = getCityAreaGame(key, cityCode, p.Type, user.Vip)
			if err != nil {
				LogClient.Error(b.DatabaseError(err.Error()))
				return
			}
			if len(value) != 0 {
				LogClient.Debug(fmt.Sprintf("市级city_code:%v的缓存不存在,但从mysql里获取到了", cityCode))
			}
		} else {
			LogClient.Debug(fmt.Sprintf("市级city_code:%v的缓存存在,且不为空", cityCode))
		}
	}
	b.Res.Data = value
	b.ResponseSuccess()
	return
}

//获取市级的游戏列表
func getCityAreaGame(key string, cityCode interface{}, typ, userVip int64) ([]orm.Params, error) {
	//根据玩家所在的地区列表游戏列表
	areaGameList, err := client.ListAreaGame(cityCode)
	if err != nil {
		LogClient.Error(fmt.Sprintf("获取市级区域city_code:%v游戏出错:%v", cityCode, err))
		return areaGameList, err
	}
	//如果区域游戏为空,则有全国游戏代替
	if len(areaGameList) == 0 {
		areaGameList, err = client.ListNationalGame()
		if err != nil {
			LogClient.Error(fmt.Sprintf("获取全国区域city_code:%v游戏出错:%v", cityCode, err))
			return areaGameList, err
		}
	}

	//获取全部游戏
	allGameList, err := client.ListAllGame(typ)
	if err != nil {
		LogClient.Error(fmt.Sprintf("获取全部游戏出错:%v", err))
		return allGameList, err
	}

	//在所有游戏里剔除区域游戏,然后再把所有游戏接在区域游戏的后面返回给客户端
	tmpArea := make(map[interface{}]orm.Params)
	var tmp []orm.Params
	tmp = append(tmp, areaGameList...) //区域游戏放在前面

	//efficient solution
	for _, v := range areaGameList { //区域游戏
		tmpArea[v["game_id"]] = v
	}

	for _, v := range allGameList {
		if _, ok := tmpArea[v["game_id"]]; !ok { //所有游戏列表中如果不在区域游戏中列表,就加入，接在后面
			v["position"] = OrderCode //不是区域里的游戏，所以全部排序，排在最后
			tmp = append(tmp, v)
		}
	}
	var t []orm.Params
	for _, v := range tmp {
		vip, _ := strconv.ParseInt(fmt.Sprintf("%v", v["user_vip"]), 10, 64)
		if vip <= userVip {
			t = append(t, v)
		}
	}
	err = SetSliceCache(key, t, CacheExpire)
	if err != nil {
		LogClient.Error(fmt.Sprintf("存储到缓存里报错:%v\n", err))
	}
	return t, err
}

//获取县级的游戏列表
func getCountyAreaGame(key string, cityCode interface{}, typ, userVip int64) ([]orm.Params, error) {
	//根据玩家所在的地区列表游戏列表
	areaGameList, err := client.ListAreaGame(cityCode)
	if err != nil {
		LogClient.Error(fmt.Sprintf("获取县级区域city_code:%v游戏出错:%v", cityCode, err))
		return areaGameList, err
	}

	//说明县级没有游戏列表,直接返回
	if len(areaGameList) == 0 {
		//县级没有游戏列表，都要把它存在缓存里,只不过缓存为空而已
		SetSliceCache(key, areaGameList, CacheExpire)
		return areaGameList, nil
	}

	//--------------------下面是县级有游戏的情况--------------------

	//获取全部游戏
	allGameList, err := client.ListAllGame(typ)
	if err != nil {
		LogClient.Error(fmt.Sprintf("获取全部游戏出错:%v", err))
		return allGameList, err
	}

	//在所有游戏里剔除区域游戏,然后再把所有游戏接在区域游戏的后面返回给客户端
	tmpArea := make(map[interface{}]orm.Params)
	var tmp []orm.Params
	tmp = append(tmp, areaGameList...) //区域游戏放在前面

	//efficient solution
	for _, v := range areaGameList { //区域游戏
		tmpArea[v["game_id"]] = v
	}

	for _, v := range allGameList {
		if _, ok := tmpArea[v["game_id"]]; !ok { //所有游戏列表中如果不在区域游戏中列表,就加入，接在后面
			v["position"] = OrderCode //不是区域里的游戏，所以全部排序，排在最后
			tmp = append(tmp, v)
		}
	}
	var t []orm.Params
	for _, v := range tmp {
		vip, _ := strconv.ParseInt(fmt.Sprintf("%v", v["user_vip"]), 10, 64)
		if vip <= userVip {
			t = append(t, v)
		}
	}
	err = SetSliceCache(key, t, CacheExpire)
	return t, err
}

// @Title 获得大厅服务器IP
// @Description 获得大厅服务器
// @Success 0 配置信息
// @Failure 400
// @Failure 404
// @router /getlobbyserverip [post]
func (b *GameController) GetLobbyServerIP() {
	res, err := client.GetLobbyServerIpByUid(b.Uid, client.GetCurSvrGroup())
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	b.Res.Data = res
	b.ResponseSuccess()
}
